package model_Ke;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class DirectedGraph extends IGraph {

	private static final DirectedGraph UndirectedGraph = null;

	public DirectedGraph(int[][] matrix, List<Point> numberPoints) {
		super(matrix, numberPoints);
	}

	public DirectedGraph(MatrixWeight matrixWeight, List<Point> numberPoints) {
		super(matrixWeight, numberPoints);
	}

	// @Override
	// public int degIn(String u) {
	// int sum = 0;
	// for (int i = 0; i < this.size(); i++) {
	// if(numberPoints.get(i).equals(u)){
	// for (int j = 0; j < this.size(); j++) {
	// sum += matrix[j][i];
	// }
	// }
	// }
	// return sum;
	// }

	@Override
	public int deg(String u) {
		for (int i = 0; i < this.size(); i++) {
			if (numberPoints.get(i).equals(u)) {
				return degIn(i) + degOut(i);
			}
		}
		return -1;
	}

	/**
	 * Sum deg In of point
	 * 
	 * @param point
	 * @return
	 */
	public int degIn(int point) {
		int sum = 0;
		for (int i = 0; i < this.size(); i++) {
			sum += matrix[i][point];
		}
		return sum;
	}

	/**
	 * Sum deg Out of point
	 * 
	 * @param u
	 * @return
	 */
	public int degOut(int point) {
		int sum = 0;
		for (int i = 0; i < this.size(); i++) {
			sum += matrix[point][i];
		}
		return sum;
	}

	@Override
	public int numberSumEdge() {
		int sum = 0;
		for (int i = 0; i < this.size(); i++) {
			sum += deg(numberPoints.get(i).getName());
		}
		return sum;
	}

	@Override
	public boolean addPoint(Point point) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean addPoint(String name) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void removePoint(Point point) {
		// TODO Auto-generated method stub

	}

	@Override
	public void removePoint(String name) {
		// TODO Auto-generated method stub

	}

	@Override
	public void addEdge(Point start, Point end) {
		// TODO Auto-generated method stub

	}

	@Override
	public void addEdge(String start, String end) {
		int s = 0, e = 0;
		for (int i = 0; i < this.size(); i++) {
			if (numberPoints.get(i).equals(start))
				s = i;
			if (numberPoints.get(i).equals(end))
				e = i;
		}
		matrix[s][e] = 1;

	}

	@Override
	public void removeEdge(Point start, Point end) {
		// TODO Auto-generated method stub

	}

	@Override
	public void removeEdge(String start, String end) {
		// TODO Auto-generated method stub

	}

	@Override
	public int[][] getMatrix() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getNumberPoints() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	protected void setSizeAddPoint() {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean isBipartite() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isConnection() {
		Stack<Integer> stack = new Stack<>();
		boolean visited[] = new boolean[this.size()];
		int v = 0;
		boolean cont = true;
		a: while (cont) {
			visited[v] = true;
			for (int i = 0; i < this.size(); i++) {
				if (matrix[v][i] == 1 && visited[i] == false) {
					stack.push(v);
					v = i;
					continue a;
				}
			}
			if (stack.size() != 0)
				v = stack.pop();
			else
				cont = false;
		}
		for (int i = 0; i < visited.length; i++) {
			if (visited[i] == false) {
				return false;
			}
		}
		return true;
	}

	@Override
	public boolean isConnectionStrong() {
		for (int i = 0; i < this.numberPoints.size(); i++) {
			int j = i + 1;
			if (j == this.numberPoints.size()) {
				j = 0;
			}
			if (!hasWay(numberPoints.get(i).getName(), numberPoints.get(j)
					.getName())) {
				return false;
			}
		}
		return true;
	}

	@Override
	public int countNumberConnection() {
		// TODO Auto-generated method stub
		return 0;
	}

	public boolean hasWay(String start, String end) {
		// List<Integer> stackWay = new ArrayList<>();
		Stack<Integer> stack = new Stack<>();
		int s = 0, e = 0;
		for (int i = 0; i < this.size(); i++) {
			if (numberPoints.get(i).equals(start))
				s = i;
			if (numberPoints.get(i).equals(end))
				e = i;
		}
		int v = s;
		boolean cont = true;
		int m[][] = matrix;
		a: while (cont) {
			for (int i = 0; i < this.size(); i++) {
				if (m[v][i] == 1) {
					if (i == e)
						return true;
					else {
						stack.push(v);
						m[v][i] = 0;
						v = i;
						continue a;
					}
				}
			}
			if (stack.size() != 0) {
				v = stack.pop();
				continue a;
			} else {
				cont = false;
			}
		}
		return false;
	}

	@Override
	public boolean isEuler() {
		if (!isConnection())
			return false;
		else
			for (int i = 0; i < this.numberPoints.size(); i++) {
				if (degIn(i) != degOut(i))
					return false;
			}

		return true;
	}

	@Override
	public String findEuler() {
		return null;
	}

	@Override
	public void removeEdge(int col, int row) {
		// TODO Auto-generated method stub

	}

	@Override
	public int deg(int u) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean hasWayEuler() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public String findWayEuler() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isTree() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int numberWay(int s, int e) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<Integer> mathEccentricity() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public FreeTree prim() {
		// TODO Auto-generated method stub
		return null;
	}

	public MatrixWeight matrixWayShort() {
		MatrixWeight temp = this.matrixWeight;

		double[][] p = new double[size()][size()];
		// MatrixWeight p = new MatrixWeight(size());
		for (int i = 0; i < p.length; i++) {
			for (int j = 0; j < p.length; j++) {
				if (this.matrixWeight.getWeight(i, j) != Double.POSITIVE_INFINITY) {
					p[i][j] = j;
				} else {
					p[i][j] = Double.POSITIVE_INFINITY;
				}
			}
		}
		MatrixWeight p2 = new MatrixWeight(p);

		String temp2 = "\n ";

		for (int i = 0; i < matrix.length; i++) {
			temp2 = temp2 + "\n" + numberPoints.get(i);
			for (int j = 0; j < matrix.length; j++) {
				temp2 = temp2 + " " + matrix[i][j];
			}
		}
		System.out.println(temp + "\n");

		for (int k = 0; k < this.matrixWeight.size(); k++) {
			for (int i = 0; i < this.matrixWeight.size(); i++) {
				for (int j = 0; j < this.matrixWeight.size(); j++) {
					if (temp.getWeight(i, j) > (temp.getWeight(i, k) + temp
							.getWeight(k, j))) {
						temp.setWeight(i, j,
								temp.getWeight(i, k) + temp.getWeight(k, j));
						p[i][j] = p[i][k];
					} else {
						temp.setWeight(i, j, temp.getWeight(i, j));
						p[i][j] = p[i][j];

					}
				}
			}
		}
		return temp;
	}
}
